package hospital.user.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.mysql.jdbc.StringUtils;
import hospital.enums.AuthStatusEnum;
import hospital.exception.HospitalException;
import hospital.helper.JwtHelper;
import hospital.model.user.Patient;
import hospital.model.user.UserInfo;
import hospital.result.ResultCodeEnum;
import hospital.user.mapper.UserInfoMapper;
import hospital.user.service.PatientService;
import hospital.user.service.UserInfoService;
import hospital.vo.user.LoginVo;
import hospital.vo.user.UserAuthVo;
import hospital.vo.user.UserInfoQueryVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author
 * @description:
 * @create 2023/4/3 15:24
 */
@Service
public class UserInfoServiceImpl  extends
        ServiceImpl<UserInfoMapper, UserInfo> implements UserInfoService  {

    @Autowired
    private RedisTemplate<String,String> redisTemplate;
    @Autowired
    private PatientService patientService;

    /**
     * @Author yang
     * @Description //TODO 用户的登录验证
     * @Date 15:50 2023/4/3
     * @Param [user]
     * @return
     **/
    @Override
    public Map<String, Object> login(LoginVo user) {
        //从用户中，获取手机号和验证码
        String phone = user.getPhone();
        String code = user.getCode();

        //判断手机号和验证码 ，空则抛出异常
        if(StringUtils.isNullOrEmpty(phone)||StringUtils.isNullOrEmpty(code)){
            throw new HospitalException(ResultCodeEnum.CODE_ERROR);
        }
//        TODD 进行手机验证码与输入验证码的校验 ,不相等，则抛出异常
//        if(!code.equals(redisTemplate.opsForValue().get(phone))){
//            throw new HospitalException(ResultCodeEnum.CODE_ERROR);
//        }

        //绑定手机号码
        //如果是微信扫码登录，则Openid有值，则绑定手机号码，
        // 执行后userInfo就!=null了不会走70行的手机号登录
        UserInfo userInfo=null;
        //如果为空,绑定手机号
        if(!StringUtils.isNullOrEmpty(user.getOpenid())){
            userInfo=this.getUesrInfoByOpenid(user.getOpenid());
            if(null!=userInfo){
                userInfo.setPhone(user.getPhone());
                //更新数据库
                this.updateById(userInfo);
            }else {
                throw new HospitalException(ResultCodeEnum.DATA_ERROR);
            }
        }

        //如果userinfo为空，进行正常手机登录
        if(userInfo == null) {
            //判断是否第一次登录：根据手机号查询数据库，如果不存在相同手机号就是第一次登录
            QueryWrapper<UserInfo> wrapper = new QueryWrapper<>();
            wrapper.eq("phone",phone);
            userInfo = baseMapper.selectOne(wrapper);
            //如果userInfo不为null，则不执行if里面，直接去93行执行代码
            if(userInfo == null) { //第一次使用这个手机号登录
                //添加信息到数据库
                userInfo = new UserInfo();
                userInfo.setName("");
                userInfo.setPhone(phone);
                userInfo.setStatus(1);
                baseMapper.insert(userInfo);
            }
        }
        //不是第一次登录，则将用户名和token保存到map中
        //判断是否是可用状态
        if(userInfo.getStatus()==0){
            throw new HospitalException(ResultCodeEnum.LOGIN_DISABLED_ERROR);
        }

        //不是第一次登录，直接登录。假设用户是userInfo == null手机号登录的，并且已经注册过不用走75行的代码了，直接走下面的即可。
        //返回登录信息
        //返回登录用户名
        //返回token信息，token信息是用来返回给前台的，执行操作时判断用户是否登录状态，可以设置过期时间用session一样

        //返回页面显示名称
        Map<String,Object> map=new HashMap<>();
        String name = userInfo.getName();
        //如果这个用户登录后没有去设置真实姓名，则name为空，那我们就设置该用户它在前端显示的名字为昵称
        if(StringUtils.isNullOrEmpty(name)){
            name=userInfo.getNickName();
        }
        //如果这个用户登录后也没有设置昵称，则name还是空，那我们就设置该用户它在前端显示的名字为它的手机号
        if(StringUtils.isNullOrEmpty(name)){
            name=userInfo.getPhone();
        }

        System.out.println(name);
        //返回用户名和token
        map.put("name",name);

        //TODD 通过jwt生成token生成
        String token = JwtHelper.createToken(userInfo.getId(), name);
        map.put("token",token);
        return map;
    }

    /**
     * @Author yang
     * @Description //TODO //判断数据库是否存在微信的扫描人信息
     *             //根据openid判断 ,如果存在用户的信息，则会重复添加
     * @Date 16:23 2023/4/3
     * @Param [openid]
     * @return
     **/
    @Override
    public UserInfo getUesrInfoByOpenid(String openid) {
        QueryWrapper<UserInfo> wrapper=new QueryWrapper<>();
        wrapper.eq("openid",openid);
        UserInfo userInfo = baseMapper.selectOne(wrapper);
        return userInfo;
    }

    /**
     * @Author yang
     * @Description //TODO 用户认证接口
     * @Date 10:27 2023/4/3
     * @Param [userId, authVo]
     * @return
     **/
    @Override
    public void userAuth(Long userId, UserAuthVo authVo) {

        //1.通过userId获取到userInfo
        UserInfo userInfo = baseMapper.selectById(userId);
        //对userinfo内的信息，进行更新
        //设置用户的真实姓名
        userInfo.setName(authVo.getName());
        //其他信息
        userInfo.setCertificatesNo(authVo.getCertificatesNo());
        userInfo.setCertificatesType(authVo.getCertificatesType());
        userInfo.setCertificatesUrl(authVo.getCertificatesUrl());
        userInfo.setAuthStatus(AuthStatusEnum.AUTH_RUN.getStatus());
        //保存用户信息的更新
        baseMapper.updateById(userInfo);
    }

    /**
     * @Author yang
     * @Description //TODO 后台分页查询用户列表
     * @Date 21:27 2023/4/3
     * @Param [page, limit, queryVo]
     * @return
     **/
    @Override
    public Page<UserInfo> findALl(Integer page, Integer limit, UserInfoQueryVo queryVo) {

        //设置分页条件
        Page<UserInfo> pageParams=new Page<>(page,limit);
        //获取查询条件
        //用户名称
        String name = queryVo.getKeyword();
        //用户状态
        Integer status = queryVo.getStatus();
        //认证状态
        Integer authStatus = queryVo.getAuthStatus();
        //开始时间
        String createTimeBegin = queryVo.getCreateTimeBegin();
        //结束时间
        String createTimeEnd = queryVo.getCreateTimeEnd();

        //封装查询条件
        QueryWrapper<UserInfo> wrapper=new QueryWrapper<>();
        if(!StringUtils.isNullOrEmpty(name)){
            wrapper.like("name",name);
        }
        if(null!=status){
            wrapper.eq("status",status);
        }
        if(null!=authStatus){
            wrapper.eq("auth_status",authStatus);
        }
        if(!StringUtils.isNullOrEmpty(createTimeBegin)){
            wrapper.ge("create_time",createTimeBegin);
        }
        if(!StringUtils.isNullOrEmpty(createTimeEnd)){
            wrapper.le("create_time",createTimeEnd);
        }

        Page<UserInfo> userInfoPage = baseMapper.selectPage(pageParams, wrapper);

        //封装用户状态和认证状态
        userInfoPage.getRecords().stream().forEach( item ->{
            this.paketUserInfo(item);
        });
        return userInfoPage;
    }

    /**
     * @Author yang
     * @Description //TODO 用户的锁定
     * @Date 15:04 2023/4/3
     * @Param [id, status]
     * @return
     **/
    @Override
    public void lock(Long id, Integer status) {
        if(status.intValue()==1 || status.intValue()==0){
            UserInfo userInfo = baseMapper.selectById(id);
            userInfo.setStatus(status);
            baseMapper.updateById(userInfo);
        }
    }

    /**
     * @Author yang
     * @Description //TODO 查询用户详情
     * @Date 16:30 2023/4/3
     * @Param [id]
     * @return
     **/
    @Override
    public Map<String, Object> show(Long id) {
        Map<String, Object> map=new HashMap<>();
        //根据id，查询用户信息
        UserInfo userInfo = baseMapper.selectById(id);
        //封装其他属性
        this.paketUserInfo(userInfo);
        map.put("userInfo",userInfo);

        //查询就诊人列表
        List<Patient> patientList = patientService.findAllByUserId(id);
        map.put("patientList",patientList);
        return map;
    }

    /**
     * @Author yang
     * @Description //TODO 认证审批
     * @Date 16:36 2023/4/3
     * @Param [id, authStatus]
     * @return
     **/
    @Override
    public void approval(Long id, Integer authStatus) {
        UserInfo userInfo = baseMapper.selectById(id);
        if(authStatus.intValue()==2 ||authStatus.intValue()==-1){
            userInfo.setAuthStatus(authStatus);
            baseMapper.updateById(userInfo);
        }
    }

    /**
     * @Author yang
     * @Description //TODO //封装用户状态和认证状态
     * @Date 21:39 2023/4/3
     * @Param [item]
     * @return
     **/
    private void paketUserInfo(UserInfo item) {
        item.getParam().put("authStatusString",AuthStatusEnum.getStatusNameByStatus(item.getAuthStatus()));
        String statusString=item.getStatus()==0?"锁定":"正常";
        item.getParam().put("statusString",statusString);
    }
}
